package com.csyf.manager.controller.api;

import com.csyf.manager.channel.base.PaymentVo;
import com.csyf.manager.channel.base.ServiceEnum;
import com.csyf.manager.channel.base.TrandeVo;
import com.csyf.manager.common.CommonConst;
import com.csyf.manager.entity.SysMerchant;
import com.csyf.manager.entity.SysTradeType;
import com.csyf.manager.exception.ApiValidateException;
import com.csyf.manager.service.SysMerchBiz;
import com.csyf.manager.service.impl.RedisService;
import com.csyf.manager.utils.NumberHelpler;
import com.csyf.manager.utils.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;

import java.math.BigDecimal;

/**
 * @Author: Enzo
 * @Date: 2018/4/8 16:37
 */
@Slf4j
@Component
public class ApiBaseController {


    @Autowired
    private SysMerchBiz sysMerchBiz;


    @Autowired
    private RedisService redisService;

    private static final String SIGN_KEY = "signkey:";
    private static final String SERVICE_TYPE = "service:";
    private static final String PAYMENT_WHILE_IP = "payment_whileip:";
    private static final String TRADE_WHILE_IP = "trade_whileip:";
    private static final String PAYMENT_WHILE_BANKCARD = "payment_while_bankcard:";

    /**
     * 校验代付IP是否在白名单内
     *
     * @param reqIp
     * @param mch_id
     */
    protected void validatePaymentWhileIp(String reqIp, String mch_id) throws ApiValidateException {
        validatePaymentIP(reqIp, mch_id, PAYMENT_WHILE_IP);
    }


    /**
     * 校验交易IP是否在白名单内
     *
     * @param reqIp
     * @param mch_id
     */
    protected void validateTradeWhileIp(String reqIp, String mch_id) throws ApiValidateException {
        validateTradeIp(reqIp, mch_id, TRADE_WHILE_IP);
    }


    /**
     * 校验IP
     *
     * @param reqIp
     * @param mch_id
     * @param type
     * @throws ApiValidateException
     */
    private void validateTradeIp(String reqIp, String mch_id, String type) throws ApiValidateException {
        log.info("[{}]请求IP[{}]】，交易类型【{}】", mch_id, reqIp, type);
        String ipkey = type + mch_id;
        Boolean isexist = redisService.exist(ipkey);
        //存在key则判断ip值是否合法，不存在则不判断
        if (isexist) {
            //获取key所在的值列表
            boolean validateip = redisService.validateip(mch_id, reqIp, PAYMENT_WHILE_IP);
            if (!validateip) {
                log.info("[{}]请求IP[{}]不合法", mch_id, reqIp);
                throw new ApiValidateException("IP不合法");
            }
        }
    }

    /**
     * 校验IP
     *
     * @param reqIp
     * @param mch_id
     * @param type
     * @throws ApiValidateException
     */
    private void validatePaymentIP(String reqIp, String mch_id, String type) throws ApiValidateException {
        log.info("[{}]请求IP[{}]】，交易类型【{}】", mch_id, reqIp, type);
        String ipkey = type + mch_id;
        Boolean isexist = redisService.exist(ipkey);
        //存在key则判断ip值是否合法，不存在则不判断
        if (isexist) {
            // 表单代付提交请求，IP地址为本机
            if (!CommonConst.LOCAL_IP.equals(reqIp)) {
                //获取key所在的值列表
                boolean validateip = redisService.validateip(mch_id, reqIp, PAYMENT_WHILE_IP);
                if (!validateip) {
                    log.info("[{}]请求IP[{}]不合法", mch_id, reqIp);
                    throw new ApiValidateException("IP不合法");
                }
            }

        } else {
            log.info("[{}]请求IP[{}]不合法", mch_id, reqIp);
            throw new ApiValidateException("IP不合法");
        }
    }


    /**
     * 校验代付银行卡号是否在白名单内
     *
     * @param bankCard
     * @param mch_id
     */
    protected void validatePaymentBankCard(String bankCard, String mch_id) throws ApiValidateException {
        validateBankCard(bankCard, mch_id, PAYMENT_WHILE_BANKCARD);
    }

    /**
     * 校验银行卡
     *
     * @param bankCard
     * @param mch_id
     * @param type
     * @throws ApiValidateException
     */
    private void validateBankCard(String bankCard, String mch_id, String type) throws ApiValidateException {
        String bankcardkey = type + mch_id;
        Boolean isexist = redisService.exist(bankcardkey);

        //存在key则校验银行卡号是否合法，不存在则不判断
        if (isexist) {
            boolean validateBankcard = redisService.validateBankcard(mch_id, bankCard, PAYMENT_WHILE_BANKCARD);
            if (!validateBankcard) {
                log.info("[{}]代付请求银行卡不合法[{}]", mch_id, bankCard);
                throw new ApiValidateException("代付银行卡号与报备卡号不一致");
            }
        }

    }


    /**
     * 判断校验器 的校验结果
     *
     * @param bindingResult
     * @throws ApiValidateException
     */
    protected void validateHibernate(BindingResult bindingResult) throws ApiValidateException {
        if (bindingResult.hasErrors()) {
            for (ObjectError error : bindingResult.getAllErrors()) {
                throw new ApiValidateException(error.getDefaultMessage());
            }
        }
    }


    /**
     * 判断商户号是否合法
     *
     * @param mch_id
     * @throws ApiValidateException
     */
    protected void validmerchid(String mch_id) throws ApiValidateException {
        String signkey = SIGN_KEY + mch_id;
        Boolean aBoolean = redisService.exist(signkey);
        if (!aBoolean) {
            SysMerchant sysAgent = sysMerchBiz.queryAgentByMerchantNo(mch_id);

            if (null == sysAgent) {
                throw new IllegalArgumentException("商户号不存在");
            }
            redisService.set(signkey, sysAgent.getMerchSignkey());
        }
    }


    /**
     * 判断service 是否是存在
     *
     * @param mch_id
     * @param service
     * @throws ApiValidateException
     */
    protected void validservice(String mch_id, String service) throws ApiValidateException {

        String key = String.format(SERVICE_TYPE + "%s:%s", mch_id, service);

        boolean exist = redisService.exist(key);
        if (!exist) {
            SysTradeType sysAgent = sysMerchBiz.queryTradeType(mch_id, service);
            if (null == sysAgent) {
                throw new IllegalArgumentException("交易类型错误或者未配置");
            }

            if (sysAgent.getRate().compareTo(BigDecimal.ZERO) <= 0) {
                throw new IllegalArgumentException("请联系管理员配置费率");
            }
            redisService.set(key, "1");
        }
    }


    /**
     * 校验签名
     *
     * @param object
     * @param mch_id
     * @param sign
     * @throws ApiValidateException
     */
    protected void validsign(Object object, String mch_id, String sign) throws ApiValidateException {
        log.info("{}:{}", this.getClass().getSimpleName(), object.toString());
        String agentSignKey = getAgentSignKey(mch_id);
        log.info("[{}] 参数进行验签:如下", mch_id);
        boolean b = SignUtils.objectVerifySign(object, agentSignKey, sign);
        if (!b) {
            throw new IllegalArgumentException("验签失败");
        }
    }


    /**
     * 校验类型所需要的参数
     *
     * @param vo
     * @throws ApiValidateException
     */
    protected void validServiceParam(TrandeVo vo) throws ApiValidateException {

        String service = vo.getService();
//        ServiceEnum serviceEnum = ServiceEnum.valueOf(service);
//        switch (serviceEnum) {
//            case XFZF_JD_H5:
//            case SAND_FAST:
//            case LYDZ_WECHAT_SM:
//            case LYDZ_ALI_SM:
//            case LYDZ_WECHAT_WAP:
//            case LYDZ_ALI_WAP:
//            case XZ_ALI_SM:
//            case TS_FAST:
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址[return_url]不能为空");
//                }
//                break;
//            case SYX_WEB:
//            case SAND_WEB:
//            case YYT_WEB:
//                if (StringUtils.isBlank(vo.getBankno())) {
//                    throw new IllegalArgumentException("银行简称[bankno]不能为空");
//                }
//                break;
//            case HYR_FAST:
//                if (StringUtils.isBlank(vo.getCardNo())) {
//                    throw new IllegalArgumentException("银行卡号[cardNo]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址[return_url]不能为空");
//                }
//                break;
//            case HYR_WEB:
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankno())) {
//                    throw new IllegalArgumentException("银行简称[bankno]不能为空");
//                }
//                break;
//            case TS_WAP:
//                if (StringUtils.isBlank(vo.getCardNo())) {
//                    throw new IllegalArgumentException("银行卡号[cardNo]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址[return_url]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankno())) {
//                    throw new IllegalArgumentException("银行简称[bankno]不能为空");
//                }
//                break;
//            case PA_WEIXIN_H5:
//                if (vo.getOut_trade_no().length() < 20 || vo.getOut_trade_no().length() > 32) {
//                    throw new IllegalArgumentException("订单号[out_trade_no]长度不能小于20位且大于32位)");
//                }
//                if (StringUtils.isBlank(vo.getRealIp())) {
//                    throw new IllegalArgumentException("用户Ip[realIp]不能为空");
//                }
//                break;
//            case ZG_WAP:
//            case ZG_WAP_B:
//                if (StringUtils.isBlank(vo.getBankno())) {
//                    throw new IllegalArgumentException("银行简称[bankno]不能为空");
//                }
//                break;
//            case IBUY_FAST:
//            case ZG_QQ_SM:
//                if (StringUtils.isBlank(vo.getRealIp())) {
//                    throw new IllegalArgumentException("用户Ip[realIp]不能为空");
//                }
//                break;
//            case TXZF_H5:
//                if (StringUtils.isBlank(vo.getCardNo())) {
//                    throw new IllegalArgumentException("银行卡号[cardNo]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址[return_url]不能为空");
//                }
//                break;
//
//            case JIEBAO_WEB:
//                if (StringUtils.isBlank(vo.getBankno())) {
//                    throw new IllegalArgumentException("银行简称[bankno]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址[return_url]不能为空");
//                }
//                break;
//
//            case DS_FAST:
//                if (StringUtils.isBlank(vo.getCardNo())) {
//                    throw new IllegalArgumentException("银行卡号[cardNo]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址[return_url]不能为空");
//                }
//                break;
//            case DS_WEB:
//                if (StringUtils.isBlank(vo.getBankno())) {
//                    throw new IllegalArgumentException("银行简称[bankno]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址[return_url]不能为空");
//                }
//                break;
//            case JFT_ALI_SM:
//                if (StringUtils.isBlank(vo.getReturn_url())) {
//                    throw new IllegalArgumentException("支付后跳转地址[return_url]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getRealIp())) {
//                    throw new IllegalArgumentException("用户Ip[realIp]不能为空");
//                }
//                break;
//            case TY_ALI_SM:
//                if (StringUtils.isBlank(vo.getRealIp())) {
//                    throw new IllegalArgumentException("用户Ip[realIp]不能为空");
//                }
//                break;
//        }

    }


    /**
     * 校验代付参数
     *
     * @param vo
     * @throws ApiValidateException
     */
    protected void validDfServiceParam(PaymentVo vo) throws ApiValidateException {

        // 同一类型，同一商户号，只能1s 中代付一笔
        String yyyyMMddHHmmss = "payment_interval:" + vo.getMch_id() + "_" + vo.getService();
        boolean exist = redisService.exist(yyyyMMddHHmmss);
        if (exist) {
            long l = System.currentTimeMillis();
            String s = redisService.get(yyyyMMddHHmmss);
            if (l - Long.parseLong(s) < 500) {
                throw new IllegalArgumentException("代付过于频繁，请重新发起");
            }
        }
        redisService.set(yyyyMMddHHmmss, String.valueOf(System.currentTimeMillis()), 24 * 60 * 60);

        String service = vo.getService();
//        ServiceEnum serviceEnum = ServiceEnum.valueOf(service);
//        switch (serviceEnum) {
//            case YKT_DF_NO:
//            case YKT_DF_DZ:
//                if (StringUtils.isBlank(vo.getPhoneNo())) {
//                    throw new IllegalArgumentException("持卡人手机号[phoneNo]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getIdcard())) {
//                    throw new IllegalArgumentException("持卡人身份证[idcard]不能为空");
//                }
//                break;
//            case SYX_DF:
//            case BPAY_ALI_DF_NO:
//            case BPAY_ALI_DF_DZ:
//            case KUBAO_WEB_DF_NO:
//            case KUBAO_WEB_DF_DZ:
//                if (StringUtils.isBlank(vo.getBankBranchname())) {
//                    throw new IllegalArgumentException("支行名称[bankBranchname]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankProvince())) {
//                    throw new IllegalArgumentException("开户省份[bankProvince]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankCity())) {
//                    throw new IllegalArgumentException("开户地区[bankCity]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankCode())) {
//                    throw new IllegalArgumentException("银行简称[bankCode]不能为空");
//                }
//                break;
//            case HYR_FAST_DF_NO:
//            case HYR_FAST_DF_DZ:
//                if (StringUtils.isBlank(vo.getBankCode())) {
//                    throw new IllegalArgumentException("银行简称[bankCode]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getIdcard())) {
//                    throw new IllegalArgumentException("身份证[idcard]不能为空");
//                }
//                break;
//            case JIEBAO_WEB_DF_NO:
//            case JIEBAO_WEB_DF_DZ:
//                if (StringUtils.isBlank(vo.getBankBranchname())) {
//                    throw new IllegalArgumentException("支行名称[bankBranchname]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankCode())) {
//                    throw new IllegalArgumentException("银行简称[bankCode]不能为空");
//                }
//                break;
//            case JC_DF_DZ:
//            case JC_DF_NO:
//                if (vo.getOut_trade_no().length() > 11) {
//                    throw new IllegalArgumentException("订单号长度不能大于11位");
//                }
//            case HC_WEB:
//                if (vo.getOut_trade_no().length() > 20) {
//                    throw new IllegalArgumentException("订单号长度不能大于20位");
//                }
//                break;
//            case HC_WEB_DF_NO:
//            case HC_WEB_DF_DZ:
//                if (vo.getOut_trade_no().length() > 20) {
//                    throw new IllegalArgumentException("订单号长度不能大于20位");
//                }
//                if (StringUtils.isBlank(vo.getBankCode())) {
//                    throw new IllegalArgumentException("银行简称[bankCode]不能为空");
//                }
//                break;
//            case TS_WAP_DF_NO:
//            case TS_WAP_DF_DZ:
//            case TS_FAST_DF_NO:
//            case TS_FAST_DF_DZ:
//                if (StringUtils.isBlank(vo.getBankCode())) {
//                    throw new IllegalArgumentException("银行简称[bankCode]不能为空");
//                }
//                break;
//            case SQ_ALI_DF_NO:
//            case SQ_ALI_DF_DZ:
//                if (StringUtils.isBlank(vo.getBankCode())) {
//                    throw new IllegalArgumentException("银行简称[bankCode]不能为空");
//                }
//                break;
//            case TDF_WAP_DF_NO:
//            case TDF_WAP_DF_DZ:
//                if (StringUtils.isBlank(vo.getBankCode())) {
//                    throw new IllegalArgumentException("银行简称[bankCode]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankProvince())) {
//                    throw new IllegalArgumentException("开户省份[bankProvince]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankCity())) {
//                    throw new IllegalArgumentException("开户地区[bankCity]不能为空");
//                }
//                break;
//            case CX_ALI_DF_NO:
//            case CX_ALI_DF_DZ:
//                if (StringUtils.isBlank(vo.getBankProvince())) {
//                    throw new IllegalArgumentException("银行所在省[bankProvince]不能为空");
//                }
//                if (StringUtils.isBlank(vo.getBankCity())) {
//                    throw new IllegalArgumentException("银行所在市[bankCity]不能为空");
//                }
//                break;
//        }

    }

    /**
     * 校验最大金额
     *
     * @param total_free
     * @param service
     * @throws ApiValidateException
     */
    protected void validatetotalFree(String total_free, String service) throws ApiValidateException {

        boolean number = NumberHelpler.isNumber(total_free);
        if (!number) {
            throw new IllegalArgumentException("不是有效金额");
        }
    }

    /**
     * 获取代理商的秘钥
     *
     * @param mch_id
     * @return
     */
    protected String getAgentSignKey(String mch_id) {

        String s = redisService.get(SIGN_KEY + mch_id);
        return s;
    }
}
